﻿namespace EasyWeb.Test
{
    using System.Linq;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    [TestClass]
    public class EWStateBag_Test
    {
        [TestMethod]
        public void AllTypes_Test()
        {
            var bag = new EWStateBag();

            var complex = new ComplexObject();

            bag.Set("Value", 100);
            bag.Set("Reference", "aaa");
            bag.Set("Complex", complex);
            bag.Set("Nullable", new int?(200));
            bag.Set("ValueNull", default(int));
            bag.Set("ReferenceNull", default(string));
            bag.Set("ComplexNull", default(ComplexObject));
            bag.Set("NullableNull", default(int?));

            Assert.AreEqual(100, bag.Get<int>("Value"));
            Assert.AreEqual("aaa", bag.Get<string>("Reference"));
            Assert.AreEqual(complex, bag.Get<ComplexObject>("Complex"));
            Assert.AreEqual(200, bag.Get<int?>("Nullable"));
            Assert.AreEqual(0, bag.Get<int>("ValueNull"));
            Assert.AreEqual(null, bag.Get<string>("ReferenceNull"));
            Assert.AreEqual(null, bag.Get<ComplexObject>("ComplexNull"));
            Assert.AreEqual(null, bag.Get<int?>("NullableNull"));
        }

        [TestMethod]
        public void Get_Test()
        {
            var bag = new EWStateBag();

            Assert.AreEqual(0, bag.Get<int>("ValueNull"));
            Assert.AreEqual(null, bag.Get<string>("ReferenceNull"));
            Assert.AreEqual(null, bag.Get<ComplexObject>("ComplexNull"));
            Assert.AreEqual(null, bag.Get<int?>("NullableNull"));
        }

        [TestMethod]
        public void GetDefault_Test()
        {
            var bag = new EWStateBag();

            var complex = new ComplexObject();

            Assert.AreEqual(100, bag.Get<int>("Value", () => 100));
            Assert.AreEqual("aaa", bag.Get<string>("Reference", () => "aaa"));
            Assert.AreEqual(complex, bag.Get<ComplexObject>("Complex", () => complex));
            Assert.AreEqual(200, bag.Get<int?>("Nullable", () => 200));
            Assert.AreEqual(0, bag.Get<int>("ValueNull", () => default(int)));
            Assert.AreEqual(null, bag.Get<string>("ReferenceNull", () => default(string)));
            Assert.AreEqual(null, bag.Get<ComplexObject>("ComplexNull", () => default(ComplexObject)));
            Assert.AreEqual(null, bag.Get<int?>("NullableNull", () => default(int?)));
        }

        [TestMethod]
        public void EnableChangeTracking_Test()
        {
            var bag = new EWStateBag();
            bag.EnableChangeTracking();

            bag.Set("Value", 100);
            bag.Set("Reference", "aaa");
            bag.Set("Complex", new ComplexObject());
            bag.Set("Nullable", new int?(200));
            bag.Set("ValueNull", default(int));
            bag.Set("ReferenceNull", default(string));
            bag.Set("ComplexNull", default(ComplexObject));
            bag.Set("NullableNull", default(int?));

            Assert.IsTrue(bag.HasChange);
            CollectionAssert.AreEquivalent(new[] { "Value", "Reference", "Complex", "Nullable", "ValueNull", "ReferenceNull", "ComplexNull", "NullableNull" }, bag.Changes.ToArray());
        }

        [TestMethod]
        public void DisableChangeTracking_Test()
        {
            var bag = new EWStateBag();
            bag.DisableChangeTracking();

            bag.Set("Value", 100);
            bag.Set("Reference", "aaa");
            bag.Set("Complex", new ComplexObject());
            bag.Set("Nullable", new int?(200));
            bag.Set("ValueNull", default(int));
            bag.Set("ReferenceNull", default(string));
            bag.Set("ComplexNull", default(ComplexObject));
            bag.Set("NullableNull", default(int?));

            Assert.IsFalse(bag.HasChange);
            CollectionAssert.AreEquivalent(new string[0], bag.Changes.ToArray());
        }

        public class ComplexObject { }
    }
}
